package com.jay.tools.ui;

import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.StateListDrawable;

import androidx.annotation.ColorInt;
import androidx.annotation.FloatRange;
import androidx.annotation.IntRange;
import androidx.appcompat.widget.AppCompatButton;

import android.util.AttributeSet;

import com.jay.tools.R;


/**
 * app:radius="5dp"    //设置圆角度
 * app:round="true"    //设置左右为半圆， 不用计算radius
 * app:animationDuration="200"     //设置背景切换动画时长
 * app:strokeDashGap="2dp" //设置dash
 * app:strokeDashWidth="5dp"   //设置dash width
 * app:normalStrokeWidth="2dp" //设置正常显示的边框宽度
 * app:pressedStrokeWidth="2dp"    //设置按下时显示的边框宽度
 * app:unableStrokeWidth="2dp"     //设置不可用时（enable = false）显示的边框宽度
 * app:normalStrokeColor="@android:color/white"    //设置正常显示的边框颜色
 * app:pressedStrokeColor="@android:color/white"   //设置按下时显示的边框颜色
 * app:unableStrokeColor="@android:color/white"    //设置不可用时（enable = false）显示的边框颜色
 * app:normalTextColor="@android:color/white"  //设置正常显示的文字颜色
 * app:pressedTextColor="@android:color/white" //设置按下状态显示的文字颜色
 * app:unableTextColor="@android:color/white"  //设置不可用时（enable = false）显示的文字颜色
 * app:normalBackgroundColor="@color/colorPrimaryDark" //设置正常显示的背景颜色
 * app:pressedBackgroundColor="@color/colorPrimaryDark"    //设置按下状态显示的背景颜色
 * app:unableBackgroundColor="@color/colorPrimaryDark" //设置不可用时（enable = false）背景颜色
 */

/**
 * description: Button样式
 * author: tjp
 * date: 2017/7/13 013 16:38
 */
public class ButtonStyle extends AppCompatButton {

    // text color
    private int mNormalTextColor = 0;
    private int mPressedTextColor = 0;
    private int mUnableTextColor = 0;
    ColorStateList mTextColorStateList;

    // animation duration
    private int mDuration = 0;

    // radius
    private float mRadius = 0;
    private boolean mRound;

    // stroke
    private float mStrokeDashWidth = 0;
    private float mStrokeDashGap = 0;
    private int mNormalStrokeWidth = 0;
    private int mPressedStrokeWidth = 0;
    private int mUnableStrokeWidth = 0;
    private int mNormalStrokeColor = 0;
    private int mPressedStrokeColor = 0;
    private int mUnableStrokeColor = 0;

    // background color
    private int mNormalBackgroundColor = 0;
    private int mPressedBackgroundColor = 0;
    private int mUnableBackgroundColor = 0;

    private GradientDrawable mNormalBackground;
    private GradientDrawable mPressedBackground;
    private GradientDrawable mUnableBackground;

    private int[][] states;

    StateListDrawable mStateBackground;

    public ButtonStyle(Context context) {
        this(context, null);
    }

    public ButtonStyle(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ButtonStyle(Context context, AttributeSet attrs, int defStyleAttr) {
//        android:buttonBarButtonStyle
        super(context, attrs, defStyleAttr);
        setup(attrs);
    }

    private void setup(AttributeSet attrs) {

        states = new int[4][];
        // 重点：这里在布局文件里任意给定一个android:background="@drawable/state_btn_bg_empty"即可
        Drawable drawable = getBackground();
        if (drawable != null && drawable instanceof StateListDrawable) {
            mStateBackground = (StateListDrawable) drawable;
        } else {
            mStateBackground = new StateListDrawable();
        }

        mNormalBackground = new GradientDrawable();
        mPressedBackground = new GradientDrawable();
        mUnableBackground = new GradientDrawable();

        // pressed, focused, normal, unable
        states[0] = new int[]{android.R.attr.state_enabled, android.R.attr.state_pressed};
        states[1] = new int[]{android.R.attr.state_enabled, android.R.attr.state_focused};
        states[3] = new int[]{-android.R.attr.state_enabled};
        states[2] = new int[]{android.R.attr.state_enabled};

        TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.ButtonStyle);

        // get original text color as default
        // set text color
        mTextColorStateList = getTextColors();
        int mDefaultNormalTextColor = mTextColorStateList.getColorForState(states[2], getCurrentTextColor());
        int mDefaultPressedTextColor = mTextColorStateList.getColorForState(states[0], getCurrentTextColor());
        int mDefaultUnableTextColor = mTextColorStateList.getColorForState(states[3], getCurrentTextColor());

        mNormalTextColor = a.getColor(R.styleable.ButtonStyle_normalTextColor, mDefaultNormalTextColor);
        mPressedTextColor = a.getColor(R.styleable.ButtonStyle_pressedTextColor, mDefaultPressedTextColor);
        mUnableTextColor = a.getColor(R.styleable.ButtonStyle_unableTextColor, mDefaultUnableTextColor);
        setTextColor();

        // set animation duration
        mDuration = a.getInteger(R.styleable.ButtonStyle_animationDuration, mDuration);
        mStateBackground.setEnterFadeDuration(mDuration);

        // set background color
        mNormalBackgroundColor = a.getColor(R.styleable.ButtonStyle_normalBackgroundColor, 0);
        mPressedBackgroundColor = a.getColor(R.styleable.ButtonStyle_pressedBackgroundColor, 0);
        mUnableBackgroundColor = a.getColor(R.styleable.ButtonStyle_unableBackgroundColor, 0);
        mNormalBackground.setColor(mNormalBackgroundColor);
        mPressedBackground.setColor(mPressedBackgroundColor);
        mUnableBackground.setColor(mUnableBackgroundColor);

        // set radius
        mRadius = a.getDimensionPixelSize(R.styleable.ButtonStyle_radius, 0);
//        LogUtil.e("ButtonStyle", "圆角：" + mRadius);

        mRound = a.getBoolean(R.styleable.ButtonStyle_round, false);
        mNormalBackground.setCornerRadius(mRadius);
        mPressedBackground.setCornerRadius(mRadius);
        mUnableBackground.setCornerRadius(mRadius);

        // set stroke
        mStrokeDashWidth = a.getDimensionPixelSize(R.styleable.ButtonStyle_strokeDashWidth, 0);
        mStrokeDashGap = a.getDimensionPixelSize(R.styleable.ButtonStyle_strokeDashWidth, 0);
        mNormalStrokeWidth = a.getDimensionPixelSize(R.styleable.ButtonStyle_normalStrokeWidth, 0);
        mPressedStrokeWidth = a.getDimensionPixelSize(R.styleable.ButtonStyle_pressedStrokeWidth, 0);
        mUnableStrokeWidth = a.getDimensionPixelSize(R.styleable.ButtonStyle_unableStrokeWidth, 0);
        mNormalStrokeColor = a.getColor(R.styleable.ButtonStyle_normalStrokeColor, 0);
        mPressedStrokeColor = a.getColor(R.styleable.ButtonStyle_pressedStrokeColor, 0);
        mUnableStrokeColor = a.getColor(R.styleable.ButtonStyle_unableStrokeColor, 0);
        setStroke();

        // set background
        mStateBackground.addState(states[0], mPressedBackground);
        mStateBackground.addState(states[1], mPressedBackground);
        mStateBackground.addState(states[3], mUnableBackground);
        mStateBackground.addState(states[2], mNormalBackground);
        setBackgroundDrawable(mStateBackground);
        a.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setRound(mRound);
    }

    /******************
     * stroke color
     *********************/

    public void setNormalStrokeColor(@ColorInt int normalStrokeColor) {
        this.mNormalStrokeColor = normalStrokeColor;
        setStroke(mNormalBackground, mNormalStrokeColor, mNormalStrokeWidth);
    }

    public void setPressedStrokeColor(@ColorInt int pressedStrokeColor) {
        this.mPressedStrokeColor = pressedStrokeColor;
        setStroke(mPressedBackground, mPressedStrokeColor, mPressedStrokeWidth);
    }

    public void setUnableStrokeColor(@ColorInt int unableStrokeColor) {
        this.mUnableStrokeColor = unableStrokeColor;
        setStroke(mUnableBackground, mUnableStrokeColor, mUnableStrokeWidth);
    }

    public void setStateStrokeColor(@ColorInt int normal, @ColorInt int pressed, @ColorInt int unable) {
        mNormalStrokeColor = normal;
        mPressedStrokeColor = pressed;
        mUnableStrokeColor = unable;
        setStroke();
    }

    /******************
     * stroke width
     *********************/

    public void setNormalStrokeWidth(int normalStrokeWidth) {
        this.mNormalStrokeWidth = normalStrokeWidth;
        setStroke(mNormalBackground, mNormalStrokeColor, mNormalStrokeWidth);
    }

    public void setPressedStrokeWidth(int pressedStrokeWidth) {
        this.mPressedStrokeWidth = pressedStrokeWidth;
        setStroke(mPressedBackground, mPressedStrokeColor, mPressedStrokeWidth);
    }

    public void setUnableStrokeWidth(int unableStrokeWidth) {
        this.mUnableStrokeWidth = unableStrokeWidth;
        setStroke(mUnableBackground, mUnableStrokeColor, mUnableStrokeWidth);
    }

    public void setStateStrokeWidth(int normal, int pressed, int unable) {
        mNormalStrokeWidth = normal;
        mPressedStrokeWidth = pressed;
        mUnableStrokeWidth = unable;
        setStroke();
    }

    public void setStrokeDash(float strokeDashWidth, float strokeDashGap) {
        this.mStrokeDashWidth = strokeDashWidth;
        this.mStrokeDashGap = strokeDashWidth;
        setStroke();
    }

    private void setStroke() {
        setStroke(mNormalBackground, mNormalStrokeColor, mNormalStrokeWidth);
        setStroke(mPressedBackground, mPressedStrokeColor, mPressedStrokeWidth);
        setStroke(mUnableBackground, mUnableStrokeColor, mUnableStrokeWidth);
    }

    private void setStroke(GradientDrawable mBackground, int mStrokeColor, int mStrokeWidth) {
        mBackground.setStroke(mStrokeWidth, mStrokeColor, mStrokeDashWidth, mStrokeDashGap);
    }

    /********************
     * radius
     *******************************/

    public void setRadius(@FloatRange(from = 0) float radius) {
        this.mRadius = radius;
        mNormalBackground.setCornerRadius(mRadius);
        mPressedBackground.setCornerRadius(mRadius);
        mUnableBackground.setCornerRadius(mRadius);
    }

    public void setRound(boolean round) {
        this.mRound = round;
        int height = getMeasuredHeight();
        if (mRound) {
            setRadius(height / 2f);
        }
    }

    /**
     * 1、2两个参数表示左上角，3、4表示右上角，5、6表示右下角，7、8表示左下角
     * float[] floatAuto = {20, 20, 20, 20, 0, 0, 0, 0};
     * for (int i = 0; i < floatAuto.length; i++) {
     * floatAuto[i] = DimenUtils.dp2px(mActivity, floatAuto[i]);
     * }
     */
    public void setRadius(float[] radii) {
        mNormalBackground.setCornerRadii(radii);
        mPressedBackground.setCornerRadii(radii);
        mUnableBackground.setCornerRadii(radii);
    }

    /********************
     * background color
     **********************/

    public void setStateBackgroundColor(@ColorInt int normal, @ColorInt int pressed, @ColorInt int unable) {
        mPressedBackgroundColor = normal;
        mNormalBackgroundColor = pressed;
        mUnableBackgroundColor = unable;
        mNormalBackground.setColor(mNormalBackgroundColor);
        mPressedBackground.setColor(mPressedBackgroundColor);
        mUnableBackground.setColor(mUnableBackgroundColor);
    }

    public void setNormalBackgroundColor(@ColorInt int normalBackgroundColor) {
        this.mNormalBackgroundColor = normalBackgroundColor;
        mNormalBackground.setColor(mNormalBackgroundColor);
    }

    public void setPressedBackgroundColor(@ColorInt int pressedBackgroundColor) {
        this.mPressedBackgroundColor = pressedBackgroundColor;
        mPressedBackground.setColor(mPressedBackgroundColor);
    }

    public void setUnableBackgroundColor(@ColorInt int unableBackgroundColor) {
        this.mUnableBackgroundColor = unableBackgroundColor;
        mUnableBackground.setColor(mUnableBackgroundColor);
    }

    /*******************
     * alpha animation duration
     ********************/
    public void setAnimationDuration(@IntRange(from = 0) int duration) {
        this.mDuration = duration;
        mStateBackground.setEnterFadeDuration(mDuration);
    }

    /***************
     * text color
     ***********************/
    private void setTextColor() {
        int[] colors = new int[]{mPressedTextColor, mPressedTextColor, mNormalTextColor, mUnableTextColor};
        mTextColorStateList = new ColorStateList(states, colors);
        setTextColor(mTextColorStateList);
    }

    public void setStateTextColor(@ColorInt int normal, @ColorInt int pressed, @ColorInt int unable) {
        this.mNormalTextColor = normal;
        this.mPressedTextColor = pressed;
        this.mUnableTextColor = unable;
        setTextColor();
    }

    public void setNormalTextColor(@ColorInt int normalTextColor) {
        this.mNormalTextColor = normalTextColor;
        setTextColor();

    }

    public void setPressedTextColor(@ColorInt int pressedTextColor) {
        this.mPressedTextColor = pressedTextColor;
        setTextColor();
    }

    public void setUnableTextColor(@ColorInt int unableTextColor) {
        this.mUnableTextColor = unableTextColor;
        setTextColor();
    }

    private boolean mChecked;

    public boolean isChecked() {
        return mChecked;
    }

    public void setChecked(boolean checked) {
        this.mChecked = checked;
        // true:蓝底，白字，false灰底，黑字
        mNormalBackground.setColor(checked ? mUnableBackgroundColor : mPressedBackgroundColor);
        mNormalTextColor = checked ? mUnableTextColor : mPressedTextColor;
        setTextColor();
    }

}
